import com.google.gson.Gson;
import io.socket.client.IO;
import io.socket.client.Socket;
import io.socket.emitter.Emitter;
import okhttp3.*;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.HashMap;

/**
 * 求贤若饥 虚心若愚
 *
 * @author jokerliang
 * @date 2020-05-27 15:59
 */
public class App {
    // 模拟出货测试地址，浏览器get访问即可
    //// http://saas-test.fivebao.com/api/merchant/gashapon/noAuth/test/shipment?deviceCode=shanghaiwubaokejitest
    static final Gson gson = new Gson();
    static OkHttpClient okHttpClient = new OkHttpClient();
    static MediaType json = MediaType.parse("application/json; charset=utf-8");


    public static final String PUSH_EVENT = "push_event";
    public static final String RESPONSE_EVENT = "response_event";

    private static String serviceHost = "http://saas-test.fivebao.com";
    private static String socketHost = "http://socket-test.fivebao.com";
    // 下面两个是 正式版地址
//    private static String serviceHost = "https://saas.fivebao.com";
//    private static String socketHost = "https://socket.fivebao.com";


    /**
     * 设备号，应该为每一台设备的唯一编码
     */
    static String deviceCode = "shanghaiwubaokejitest";
    static String upOrderId = "";



    public static void main(String[] args) throws URISyntaxException, InterruptedException {
        Boolean registerSuccess = register();
        /**
         * 当切仅当为true才可以进行业务逻辑，否则服务器将会拒绝此次socket连接
         */
        if (registerSuccess) {
            startClient();
        } else {
            Thread.sleep(5000);
            main(args);
            System.out.println("register操作失败，请检查日志并重试");
        }
    }

    /**
     * 第一步，发送请求注册机器
     * @throws URISyntaxException
     */
    public static Boolean register() {

        String registerUrl = serviceHost + "/api/merchant/gashapon/noAuth/register";

        RegisterEntity registerEntity = new RegisterEntity();
        registerEntity.setDeviceCode(deviceCode);
        String registerJson = gson.toJson(registerEntity);
        RequestBody requestBody = RequestBody.create(json, registerJson);
        Request request = new Request.Builder().post(requestBody).url(registerUrl).build();
        try {
            Response response = okHttpClient.newCall(request).execute();
            if (response.isSuccessful() && response.body() != null) {
                String responseJson = response.body().string();
                ResponseEntity responseEntity = gson.fromJson(responseJson, ResponseEntity.class);
                System.out.println("服务器返回注册结果: " + responseJson);
                return responseEntity.getRel();
            } else {
                return false;
            }
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

    }

    /**
     * 第二步，连接Socket,进行业务逻辑， Socket生命周期应跟随App
     * @throws URISyntaxException
     */
    public static void startClient() throws URISyntaxException {

        IO.Options options = new IO.Options();
        // deviceCode, type必填，type请写死为1
        options.query = "deviceCode=" + deviceCode + "&type=1";
        options.transports = new String[] {"websocket", "xhr-polling", "jsonp-polling"};

        final Socket socket = IO.socket(socketHost, options);


        socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
            public void call(Object... objects) {
                System.out.println("连接建立");
            }
        });

        socket.on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
            public void call(Object... objects) {
                System.out.println("连接关闭");
            }
        });

        socket.on(Socket.EVENT_ERROR, new Emitter.Listener() {
            public void call(Object... objects) {
                System.out.println("连接失败");
            }
        });


        // ---------------------下方为业务逻辑----------------------------
        /**
         *  请注意  服务端可能会推送多次重复消息，请客户端自行过滤
         */
        socket.on(PUSH_EVENT, new Emitter.Listener() {
            public void call(Object... objects) {
                Object object = objects[0];


                System.out.println("收到 消息后，必须给回波给服务器，告诉服务器接收成功，否则服务器将重试推送");
                socket.emit(RESPONSE_EVENT, "success");

                System.out.println(object.toString());
                PushMessage pushMessage = gson.fromJson(object.toString(), PushMessage.class);
                String event = pushMessage.getEvent();
                if (event.equals(PushMessage.EVENT_SHIPMENT)) {
                    ShipmentEntity shipmentEntity = gson.fromJson(pushMessage.getContent(), ShipmentEntity.class);
                    System.out.println("-------------当前出货信息-------------");
                    System.out.println("-------------"+deviceCode +"-------------");
                    System.out.println(shipmentEntity);

                    System.out.println("请注意服务端可能会推送多次重复消息，请客户端自行过滤");

                    if (upOrderId.equals(shipmentEntity.getOrderId())) {
                        // 重复消息
                        return;
                    }
                    upOrderId = shipmentEntity.getOrderId();

                    System.out.println("扭蛋机出货成功后，必须请求我方后台告知出货成功,此接口必须保证一定上报");

                    postShipmentSuccess(shipmentEntity.getOrderId(), shipmentEntity.getSpace());
                }

                if (event.equals(PushMessage.EVENT_GATE)) {
                    // 开门
                }



            }
        });

        socket.connect();
    }


    /**
     * 报告出货成功示例
     * 这个接口一定要保证百分百上报
     * 如果出错了需要有响应的重试机制
     */
    public static void postShipmentSuccess(String orderId, Integer space) {
        String url = serviceHost + "/api/merchant/gashapon/noAuth/shipment";

        GashaponShipmentReportEntity shipmentEntity = new GashaponShipmentReportEntity();
        shipmentEntity.setDeviceCode(deviceCode);
        shipmentEntity.setOrderId(orderId);
        shipmentEntity.setSpace(space);

        shipmentEntity.setShipmentResult(true);
        RequestBody requestBody = RequestBody.create(json, gson.toJson(shipmentEntity));
        Request build = new Request.Builder().post(requestBody).url(url).build();
        try {
            Response response = okHttpClient.newCall(build).execute();
            if (response.isSuccessful() && response.body() != null) {
                String responseJson = response.body().string();
                ResponseEntity responseEntity = gson.fromJson(responseJson, ResponseEntity.class);
                System.out.println("出货上报response====" + responseEntity);
                if (!responseEntity.getRel()) {
                    // 出错了需要重试
                    postShipmentSuccess(orderId, space);
                }
            } else {
                postShipmentSuccess(orderId, space);
            }
        } catch (IOException e) {
            // 出错了需要重试
            postShipmentSuccess(orderId, space);
            e.printStackTrace();
        }

    }

    /**
     * 扭蛋机 出错后需要调用此接口通知服务器
     * @throws IOException
     */
    public static void postError() {
        String url = serviceHost + "/api/merchant/gashapon/noAuth/error";
        GashaponErrorEntity gashaponErrorEntity = new GashaponErrorEntity();
        gashaponErrorEntity.setDeviceCode(deviceCode);
        gashaponErrorEntity.setErrorCode("0000000000000001");
        gashaponErrorEntity.setErrorMsg("测试错误XXXX");
        RequestBody requestBody = RequestBody.create(json, gson.toJson(gashaponErrorEntity));
        Request build = new Request.Builder().post(requestBody).url(url).build();
        try {
            Response response = okHttpClient.newCall(build).execute();
            System.out.println(response);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}
